home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 May / macformat-024.iso / Shareware City / Developers / BoxMaker++ / BoxMaker++ ƒ / boxmaker.h < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-20  |  20.8 KB  |  566 lines  |  [TEXT/KAHL]

  1. #pragma once
  2. //
  3. // This is a hack which is intended to make boxmaker compile under
  4. // both the old and the universal headers. It probably doesn't work since
  5. // (I don't have a _complete_ set of universal headers to check it with)
  6. //
  7. #if !NEW_HEADERS_AVAILABLE
  8.     #define AEEventHandlerUPP EventHandlerProcPtr
  9. #endif
  10. //
  11. // A shell's status will normally start at 'running', and then move either
  12. // to 'OApped' or 'finishing'. When a quit Apple event is received status
  13. // automatically moves to 'quitting'. The actual exit is only made when
  14. // 'EventloopHook' (a virtual function described below) returns true, and the
  15. // status is either 'finishing' or 'quitting'.
  16. //
  17. typedef enum shell_status
  18. {
  19.     shell_is_running,        // shell is running normally
  20.     shell_is_OApped,        // running normally, received OApp event
  21.     shell_is_finishing,        // started by ODOC, will quit on idle
  22.     shell_is_quitting        // Quit Apple Event received.
  23. };
  24.  
  25. typedef struct OSTypePair
  26. {
  27.     OSType type;
  28.     OSType creator;
  29. };
  30.  
  31. class boxmaker
  32. {
  33.     public:
  34.         boxmaker();
  35.         //
  36.         // A 'normal' main for a boxmaker is:
  37.         //
  38.         //        void main()
  39.         //        {
  40.         //            myboxmaker RedBand;
  41.         //            RedBand.run();
  42.         //        }
  43.         //
  44.         // the member function 'run' is needed because the 'run' can't be executed by
  45.         //
  46.         // - boxmaker's constructor because myboxmaker hasn't been constructed then
  47.         // - boxmaker's destructor because myboxmaker has already been destructed then
  48.         //
  49.         // Alternatively, myboxmaker could call 'run' at the end of its constructor,
  50.         // but there is no way to enforce that, so that method does not have any
  51.         // advantage over the one chosen here.
  52.         //
  53.         void run();
  54.  
  55.     protected:
  56.         //
  57.         // These are the actual routines to override.
  58.         //
  59.         // OpenDoc is the only one routine which _must_ be overridden.
  60.         // It should use either the information in the 'theCInfoPBRec' field or the
  61.         // information in the 'theFSSpec' field to determine the file to be processed.
  62.         // Note: OpenDoc is called before any of the 'mayEnterFolder', 'EnterFolder',
  63.         // 'ExitFolder', or 'CantEnterFolder' routines is called.
  64.         //
  65.         virtual void OpenDoc( Boolean opening) = 0L;
  66.         //
  67.         // mayEnterFolder should return a flag which indicates whether we should
  68.         // enter this particular folder. Normally you will make it to always return
  69.         // either 'true' or 'false', but you could also make it more complex.
  70.         // Thus, one can implement what Symantec calls 'shielded folders', or process
  71.         // all items of folders dropped upon the boxmaker, but not items in folders
  72.         // inside those folders. If 'mayEnterFolder' returns false, the folder is not
  73.         // entered; thus 'EnterFolder' nor 'ExitFolder' will be called for that folder.
  74.         //
  75.         virtual Boolean mayEnterFolder( Boolean opening) { return true;};
  76.         //
  77.         // EnterFolder and ExitFolder are called during a recursive descent.
  78.         // Under some circumstances you will receive both an OpenDoc and an
  79.         // EnterFolder message for folders encountered.
  80.         // The difference is that 'EnterFolder' is always called, and 'OpenDoc'
  81.         // is only called for a folder if the drop box can handle folders, as
  82.         // specified via the 'theFlags' parameter to its constructor.
  83.         //
  84.         virtual void EnterFolder( Boolean opening) {};
  85.         virtual void ExitFolder( Boolean opening) {};
  86.         //
  87.         // CantEnterFolder is called when we encounter a folder to which
  88.         // we do not have read access. In that case EnterFolder and ExitFolder
  89.         // are not called for the folder (if passFolders is set, OpenDoc will
  90.         // be called for the folder). Note: there are two different versions
  91.         // of read access, namely seeing files and seeing folders. You can
  92.         // use the 'getAccessRights' member to study the access rights.
  93.         // CantEnterFolder is called only when you have neither the see files
  94.         // nor the see folders access rights to a folder. For more complex
  95.         // selections you should override mayEnterFolder (see above)
  96.         //
  97.         virtual void CantEnterFolder( Boolean opening) {};
  98.         //
  99.         // OpenApp is called whenever the application receives an 'Open application'
  100.         // Apple Event. This happens whenever somebody opens the application without
  101.         // opening a document. Normally this is done by double-clicking the application,
  102.         // or by selecting 'Open' in the Finder's file menu after selecting the application.
  103.         // OpenApp is _not_ called when one drops files on the application, since the
  104.         // application will not receive an 'Open application' Apple event then.
  105.         // The default OpenApp simply shows the preferences dialog.
  106.         //
  107.         virtual void OpenApp() { ShowPreferences();};
  108.         //
  109.         // StartABunch and EndABunch are called at the start and end of the processing
  110.         // of an 'ODOC' event. The difference with 'OpenDoc' is that StartABunch/EndABunch
  111.         // are called exactly one time for every 'ODOC' Apple Event, not for every file
  112.         // or folder specified in that Apple Event. Also, the number of items specified
  113.         // does not include any items in subfolders, and it does not check whether the
  114.         // items are indeed processable by your application (e.g. when the 'BNDL' and 'typs'
  115.         // resources of your boxmaker do not match, or when the boxmaker is sent an
  116.         // Apple Event by AppleScript). The StartABunch/EndABunch combo can for instance
  117.         // be used to pop up a dialog requesting confirmation of a tricky operation, or
  118.         // to display and hide a progress box.
  119.         // The default versions of StartABunch and EndABunch are:
  120.         // StartABunch    : set the cursor to a watch cursor, disable all menus
  121.         // EndABunch    : reset the cursor to a NM arrow, enable all menus
  122.         //
  123.         virtual void StartABunch( long numTopLevelItems, Boolean opening);
  124.         virtual void EndABunch( long numTopLevelItems, Boolean opening);
  125.         //
  126.         // Routines to override only when one adds menus and/or menu items:
  127.         //
  128.         // If one changes the menus (boxmaker installs menu bar #128 and adds
  129.         // the desk accessories to menu #128) one should also override 'DoMenu'.
  130.         // To assist in implementing ones own 'DoMenu', the functions 'DoAppleMenu',
  131.         // 'SelectFile', 'ShowPreferences', and 'SendQuitToSelf' are provided.
  132.         //
  133.         virtual void DoMenu( long retVal);
  134.         //
  135.         // SelectFile by default lets one select _any_ file. Limiting the selection
  136.         // to certain file types can be done by adding a 'typs' resource #128 to
  137.         // the Application. For more complex selections override 'SelectFile'.
  138.         //
  139.         virtual void SelectFile();
  140.         //
  141.         // HandleDialogEvent is called whenever DialogSelect returns true.
  142.         // Normally one should just look at 'itemHit'; theDialog can be used to
  143.         // access the actual items, theEvent is passed because somebody may find
  144.         // a use for it.
  145.         // To change items from those specified in the resource (e.g. to change
  146.         // them to reflect the saved preferences), use the constructor of
  147.         // 'yourboxmaker'.
  148.         // The parameter 'theDialog' usually equals 'gMainDialog'. It is included
  149.         // for reasons of flexibility. This way, a boxmaker can display multiple
  150.         // dialogs, and determine which dialog a event is meant for.
  151.         //
  152.         virtual void HandleDialogEvent( short itemHit, DialogPtr theDialog) {};
  153.         //
  154.         // EventloopHook is called everytime through the main event loop. As all
  155.         // virtual members it can examine and change the 'myEvent' and 'gotEvent'
  156.         // fields.
  157.         // It can for instance be used in a boxmaker which does do a lengthy
  158.         // operation on files dropped on it. The 'OpenDoc' member function would
  159.         // then put the file or folder to be processed in a list, and 'EventloopHook'
  160.         // would take an item of the list, and process it partially. This way one can
  161.         // build a boxmaker which does call WaitNextEvent during processing of a file,
  162.         // and thus does not hog the Mac it is run on.
  163.         // (950116: Currently, the directory traversal routines do call WaitNextEvent
  164.         // every now and then. This was done since a lengthy traversal (e.g. of a
  165.         // one Gigabyte file server volume) already seriously hogs the Mac.
  166.         //
  167.         // EventloopHook is called directly after 'WaitNextEvent', before the event
  168.         // is processed. It is passed a Boolean which indicates whether the boxmaker
  169.         // itself would want to quit now (e.g. because the user chose 'Quit' in the
  170.         // file menu). It should return a boolean which indicates whether your boxmaker
  171.         // _can_ quit now. It is up to your boxmaker to decide what to do when its
  172.         // 'EventloopHook' is called with a value of true. Possible scenarios are
  173.         // (more or less in order of increased user-friendliness):
  174.         //
  175.         // - return true only when all file processing is done.
  176.         // - abort processing of files and return true.
  177.         // - return true and let your shell's destructor abort processing.
  178.         // - ask the user whether to abort or continue, and return false until
  179.         //   all processing is done.
  180.         // - ask the user whether to abort or continue, and return false until
  181.         //   all processing is done, and putting up a dialog explaining what is
  182.         //   going on, with a cancel button on it.
  183.         // When your EventloopHook does temporarily 'refuse' to quit when asked it
  184.         // probably is a good idea to let your opendoc handler return the value
  185.         // 'errAEEventNotHandled' after the quit request is received.
  186.         //
  187.         shell_status the_status;
  188.         virtual Boolean EventloopHook() { return true;};
  189.         //
  190.         // If your OpenDoc handler performs a lengthy operation you might want to call
  191.         // 'TimeForTea' every now and then in your OpenDoc handler.
  192.         // TimeForTea does not always call WaitNextEvent; if it doesn't call it
  193.         // it is fairly efficient, so you don't have to worry much about it slowing
  194.         // down your program.
  195.         //
  196.         void TimeForTea();
  197.         //
  198.         // the 'myEvent' field contains the last event obtained from 'WaitNextEvent'
  199.         // Thus it is available to all boxmaker's virtual member functions.
  200.         // gotEvent contains the value returned by the last call of WaitNextEvent.
  201.         // (this excludes the calls of WaitNextEvent done by TimeForTea);
  202.         //
  203.         EventRecord myEvent;
  204.         short gotEvent;
  205.         //
  206.         // These two fields contain the information about the current file
  207.         // whenever EnterFolder or OpenDoc is called. Both routines can use
  208.         // them for whatever they want to use them, as long as they do not change
  209.         // the fields ioVRefNum or ioNamePtr of 'theCInfoPBRec.hFileInfo'.
  210.         // A safer implementation of boxmaker would make these fields private, but
  211.         // then anybody wanting to use the information in a 'SetCatInfo' would have
  212.         // to allocate a CInfoPBRec and copy the information.
  213.         // When 'ExitFolder' is called the info in theCInfoPBRec does no longer
  214.         // point to the folder we are leaving.
  215.         //
  216.         // If 'theCInfoPBRec' points to a directory theSubDirID is set to the ID
  217.         // of that directory, so 'ExitFolder' may use this field to obtain the
  218.         // directory ID of the folder.
  219.         //
  220.         CInfoPBRec    theCInfoPBRec;
  221.         FSSpec        theFSSpec;
  222.         long        theSubDirID;
  223.         //
  224.         // 'Utility' functions which study theCInfoPBRec:
  225.         //
  226.         // getAccessRights assumes that theCInfoPBRec points to a directory,
  227.         // and returns the access rights, as documented in IM-V-391.
  228.         //
  229.         Boolean itsADirectory() const;
  230.         Boolean itsVisible() const;
  231.         
  232.         char getAccessRights() const;
  233.         //
  234.         // Miscellaneous utility functions:
  235.         //
  236.         static void copyStr63( const Str63 fromString, Str63 toString);
  237.         void SetUp_theFSSpec_from_theCInfoPBRec();
  238.         //
  239.         // itsProcessable checks whether 'theType' is member of the array 'theTypes',
  240.         // taking into account the situation where 'numTypes' equals -1.
  241.         // It also checks whether the file is invisible. itsProcessable can only
  242.         // be called for files. The array 'theTypes' is initialized from the 'typs'
  243.         // resource #128. This resource is supposed to contain the types of file the
  244.         // boxmaker is to process.
  245.         // This list can be restricted further by including a 'tycr' resource #128
  246.         // If it is present it should contain type-creator pairs to accept, with
  247.         // '****' a valid type or creator matching any type/creator.
  248.         //
  249.         Boolean itsProcessable() const;
  250.         Boolean matchesTypeList() const;
  251.         Boolean matchesTypeCreatorPairs() const;
  252.         //
  253.         // Functions to read the list of types accepted by this application,
  254.         // as read from the 'typs' resource #128. Present for use by subclasses.
  255.         //
  256.         const OSType *GetTheTypes() const;
  257.         short GetNumTypes() const;
  258.         //
  259.         // Functions to read the list of types accepted by this application,
  260.         // as read from the 'tycr' resource #128. Present for use by subclasses.
  261.         //
  262.         const OSTypePair *GetTheTypeCreatorPairs() const;
  263.         short GetNumTypeCreatorPairs() const;
  264.         //
  265.         // ErrorAlert puts up an alert with a message as specified by the
  266.         // resource ID of a 'STR#' resource and an index into the string list.
  267.         // It uses 'ALRT' resource # kErrorAlertID, and returns to its caller.
  268.         // ErrorAlertQuit does not return, but does an 'ExitToShell'.
  269.         //
  270.         static void ErrorAlert( short errorNo,
  271.                     short stringIndexID, short stringListID = kErrStringID);
  272.         static void ErrorAlertQuit( short errorNo,
  273.                     short stringIndexID, short stringListID = kErrStringID);
  274.         
  275.         DialogPtr        gMainDialog;
  276.         DialogRecord    myDialogRecord;
  277.         //
  278.         // amInFront() returns true when 'we' are the current front procsess.
  279.         //
  280.         Boolean amInFront() const;
  281.         //
  282.         // 'SendQuitToSelf' does just that. It is the standard routine called when the
  283.         // quit menu item is chosen.
  284.         // Similarly, 'DoAppleMenu' is the standard Apple Menu routine, 'SelectFile' the
  285.         // standard 'Open…' item handler, and 'ShowPreferences' is the standard routine
  286.         // called for the 'Preferences…' menu item. They are made accessible to subclasses
  287.         // to make overriding 'DoMenu' easier. (SelectFile is listed above; it is virtual)
  288.         //
  289.         static void SendQuitToSelf();
  290.         void DoAppleMenu( short theItem);
  291.         void ShowAbout();
  292.         void ShowPreferences();
  293.         //
  294.         // errDebug invokes the Debugger when errno is unequal to noErr
  295.         // The second form not only prints the error number, but also the
  296.         // Pascal string specified.
  297.         //
  298.         static void errDebug( OSErr errno);
  299.         static void errDebug( OSErr errno, unsigned char *errString);
  300.         //
  301.         // our own address; used to send events to self. It is obtained once
  302.         // at initialization time, and stays around for the whole lifetime of
  303.         // the boxmaker.
  304.         //
  305.         static const AEAddressDesc self;
  306.  
  307.         ProcessSerialNumber myPSN;
  308.         //
  309.         // a Handle to the standard watch cursor:
  310.         //
  311.         static const CursHandle theClock;
  312.  
  313.     private:
  314.         //
  315.         // From now (940728) on most members are made protected, so that subclasses can
  316.         // get at them (e.g. to determine kFileMenuID when DoMenu is overridden, to study
  317.         // theTypes and numTypes in a version of 'SelectFile', to do a SendQuitToSelf, etc).
  318.         // We do keep some private routines and variables, though.
  319.         //
  320.         // Four booleans, read from 'flgs' resource #128:
  321.         //
  322.         Boolean enterFolders;
  323.         Boolean passFolders;
  324.         Boolean enterInvisibles;
  325.         Boolean passInvisibles;
  326.         //
  327.         // the list of file types to look at, as read from the 'typs' resource #128
  328.         //
  329.         OSType *theTypes;
  330.         short   numTypes;
  331.         //
  332.         // the list which further restricts the type/creator pairs.
  333.         // Read from 'tycr' resource #128
  334.         //
  335.         OSTypePair *theTypeCreatorPairs;
  336.         short   numTypeCreatorPairs;
  337.  
  338.         static Boolean matches( OSType original, OSType pattern);
  339.         //
  340.         // TickCount returns a signed -> time_of_next_cup_of_tea is also signed.
  341.         //
  342.         long time_of_next_cup_of_tea;
  343.         //
  344.         // Program routines
  345.         //
  346.         void InitToolbox();
  347.         void SetUpMenus();
  348.         Boolean InitGlobals();
  349.         void GetMainDialog();
  350.         void DoMouseDown();
  351.         void DoKeyDown();
  352.         //
  353.         // Apple Event stuff
  354.         //
  355.         void InitAEVTStuff();
  356.         static OSErr GotRequiredParams( AppleEvent *theAppleEvent);
  357.  
  358.         static AEAddressDesc GetTargetToSelf();        
  359.         static void _SendDocsToSelf( AEDescList *aliasList);
  360.         static void SendODOCToSelf( FSSpec *theFileSpec);
  361.  
  362.         OSErr _HandleDocs( AppleEvent *theAppleEvent,
  363.                                 AppleEvent *reply, Boolean opening);
  364.         //
  365.         // _HandleOneDoc is actually a misnomer; if the FSSpec happens to
  366.         // indicate a folder it may end up handling multiple files.
  367.         // Anyway, it is called repeatedly by _HandleDocs, once for every file opened.
  368.         //
  369.         OSErr _HandleOneDoc( const FSSpec &aFSSpec, Boolean opening);
  370.         
  371.         OSErr _HandleADir( long dirID, Boolean opening);
  372.  
  373.         void DoHighLevelEvent();
  374.         //
  375.         // GatherInfo gets info for the file specified in 'theCInfoPBRec' and the parameters
  376.         // passed to it. The first version collects info for the file specified, the second
  377.         // one collects info for a file in the directory specified. The volume reference
  378.         // number is supposed to be present in 'theCInfoPBRec', already.
  379.         //
  380.         OSErr GatherInfo( const FSSpec &aFSSpec);
  381.         OSErr GatherInfo( long theDirID, long index);
  382.         OSErr _GatherInfo( long theDirID);
  383.         //
  384.         // FailErr displays an error alert when 'err' is not zero,
  385.         // and always returns to its caller. It is for internal use.
  386.         //
  387.         static void FailErr( OSErr err);
  388.     //
  389.     // Apple event handles can not be member functions. Making them static should help
  390.     // since the C++ calling format equals that of Pascal, but I haven't gotten it to work.
  391.     // Therefore they are made friends.
  392.     //
  393.     friend pascal OSErr HandleOAPP( AppleEvent *theAppleEvent,
  394.                             AppleEvent *reply, long handlerRefcon);
  395.     
  396.     friend pascal OSErr HandleQuit( AppleEvent *theAppleEvent,
  397.                             AppleEvent *reply, long handlerRefcon);
  398.     
  399.     friend pascal OSErr HandleODOC( AppleEvent *theAppleEvent,
  400.                             AppleEvent *reply, long handlerRefcon);
  401.     
  402.     friend pascal OSErr HandlePDOC( AppleEvent *theAppleEvent,
  403.                             AppleEvent *reply, long handlerRefcon);
  404. };
  405.  
  406. pascal OSErr HandleOAPP( AppleEvent *theAppleEvent,
  407.                         AppleEvent *reply, long handlerRefcon);
  408.  
  409. pascal OSErr HandleQuit( AppleEvent *theAppleEvent,
  410.                         AppleEvent *reply, long handlerRefcon);
  411.  
  412. pascal OSErr HandleODOC( AppleEvent *theAppleEvent,
  413.                         AppleEvent *reply, long handlerRefcon);
  414.  
  415. pascal OSErr HandlePDOC( AppleEvent *theAppleEvent,
  416.                         AppleEvent *reply, long handlerRefcon);
  417.  
  418. inline void boxmaker::FailErr( OSErr error)
  419. {
  420.     if( error != noErr)
  421.     {
  422.         ErrorAlert( error, kAEVTErr);
  423.     }
  424. }
  425.  
  426. inline Boolean boxmaker::itsADirectory() const
  427. {
  428.     return (theCInfoPBRec.hFileInfo.ioFlAttrib & ioDirMask) != 0;
  429. }
  430.  
  431. inline Boolean boxmaker::itsVisible() const
  432. {
  433.     return (theCInfoPBRec.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible) == 0;
  434. }
  435.  
  436. inline char boxmaker::getAccessRights() const
  437. {
  438.     //
  439.     // for explanation on this hard-coded constant '31', see
  440.     // the comments in boxmaker.cp, function _GatherInfo
  441.     //
  442.     return ((char *)(&theCInfoPBRec))[ 31];
  443. }
  444.  
  445. inline void boxmaker::copyStr63( const Str63 fromString, Str63 toString)
  446. {
  447.     long *from = (long *)fromString;
  448.     long *to   = (long *)toString;
  449.     
  450.     for( int i = 0; i < 16; i++)
  451.     {
  452.         *to++ = *from++;
  453.     }
  454. }
  455.  
  456. inline const OSType *boxmaker::GetTheTypes() const
  457. {
  458.     return (OSType * const)theTypes;
  459. }
  460.  
  461. inline short boxmaker::GetNumTypes() const
  462. {
  463.     return numTypes;
  464. }
  465.  
  466. inline const OSTypePair *boxmaker::GetTheTypeCreatorPairs() const
  467. {
  468.     return (const OSTypePair *)theTypeCreatorPairs;
  469. }
  470.  
  471. inline short boxmaker::GetNumTypeCreatorPairs() const
  472. {
  473.     return numTypeCreatorPairs;
  474. }
  475.  
  476. inline OSErr boxmaker::GatherInfo( const FSSpec &aFSSpec)
  477. {
  478.     copyStr63( aFSSpec.name, theFSSpec.name);
  479.  
  480. //    theCInfoPBRec.hFileInfo.ioNamePtr    = theFSSpec.name;    done for us by boxmaker::boxmaker
  481. //    theCInfoPBRec.hFileInfo.ioVRefNum    = theVRef;            done for us by boxmaker::_HandleDocs
  482. //    theCInfoPBRec.hFileInfo.ioDirID        = theDirID;            done for us by _GatherInfo
  483.     theCInfoPBRec.hFileInfo.ioFDirIndex    = 0;
  484.  
  485.     return _GatherInfo( aFSSpec.parID);
  486. }
  487.  
  488. inline OSErr boxmaker::GatherInfo( long theDirID, long index)
  489. {
  490. //    theCInfoPBRec.hFileInfo.ioNamePtr    = theFSSpec.name;    done for us by boxmaker::boxmaker
  491. //    theCInfoPBRec.hFileInfo.ioVRefNum    = theVRef;            done for us by boxmaker::_HandleDocs
  492. //    theCInfoPBRec.hFileInfo.ioDirID        = theDirID;            done for us by _GatherInfo
  493.     theCInfoPBRec.hFileInfo.ioFDirIndex    = index;
  494.  
  495.     return _GatherInfo( theDirID);
  496. }
  497.  
  498. inline void boxmaker::ShowPreferences()
  499. {
  500.     if( gMainDialog != 0)
  501.     {
  502.         ShowWindow( gMainDialog);
  503.     }
  504. }
  505.  
  506. inline void boxmaker::errDebug( OSErr errno)
  507. {
  508.     if( errno != noErr)
  509.     {
  510.         Str15 errstring;
  511.         NumToString( errno, *(Str255 *)&errstring);
  512.         DebugStr( errstring);
  513.     }
  514. }
  515.  
  516. inline void boxmaker::SetUp_theFSSpec_from_theCInfoPBRec()
  517. {
  518.     theFSSpec.vRefNum = theCInfoPBRec.hFileInfo.ioVRefNum;
  519.     theFSSpec.parID   = theCInfoPBRec.hFileInfo.ioDirID;
  520. }
  521.  
  522. inline void boxmaker::ErrorAlertQuit( short errorNo,
  523.                     short stringIndexID, short stringListID)
  524. {
  525.     ErrorAlert( errorNo, stringIndexID, stringListID);
  526.     //
  527.     // SC++ patches ExitToShell, and calls all necessary desctructors
  528.     // (at least, I like to think it does)
  529.     //
  530.     ExitToShell();
  531. }
  532.  
  533. inline Boolean boxmaker::matches( OSType original, OSType pattern)
  534. {
  535.     return ((original == pattern) || (pattern == '****'));
  536. }
  537. //
  538. // These two structures are used to parse the Handle returned from GetMenuBar
  539. // (and that is done to disable or enable all menus)
  540. //
  541. // I'm not 100% sure about this. The structure might have changed under PPC, but
  542. // I think that that would be troublesome for mixed-mode programs
  543. //
  544. #if defined(powerc) || defined (__powerc)
  545.     #pragma options align=mac68k
  546. #endif
  547.  
  548. typedef struct menulistentry
  549. {
  550.     MenuHandle theMenu;
  551.     short  menuLeftEdge;
  552. };
  553.  
  554. typedef struct menulist
  555. {
  556.     short lastHandleOffset;    // = 6 * number of menus
  557.     short rightEdge;
  558.     short unused;
  559.     
  560.     struct menulistentry theMenus[ 1];    // actually kAnyNumber
  561. };
  562.  
  563. #if defined(powerc) || defined (__powerc)
  564.     #pragma options align=reset
  565. #endif
  566.